// ==================== src/memory/service_storage.rs ====================
//! 内存服务存储实现

use async_trait::async_trait;
use nacos_core::{ServiceStorage, ServiceInstance, Result, Storage};
use std::sync::Arc;
use super::MemoryStorage;
use tracing::{debug, trace};

/// 内存服务存储实现
#[derive(Debug, Clone)]
pub struct MemoryServiceStorage {
    storage: Arc<MemoryStorage>,
}

impl MemoryServiceStorage {
    /// 创建新的内存服务存储实例
    pub fn new() -> Self {
        Self {
            storage: Arc::new(MemoryStorage::new()),
        }
    }
    
    /// 从现有存储创建
    pub fn from_storage(storage: Arc<MemoryStorage>) -> Self {
        Self { storage }
    }
    
    /// 生成服务实例键
    fn instance_key(&self, namespace: &str, group: &str, service_name: &str, instance_id: &str) -> String {
        format!("service:{}:{}:{}:{}", namespace, group, service_name, instance_id)
    }
    
    /// 生成服务键前缀
    fn service_prefix(&self, namespace: &str, group: &str, service_name: &str) -> String {
        if service_name.is_empty() {
            format!("service:{}:{}:", namespace, group)
        } else {
            format!("service:{}:{}:{}:", namespace, group, service_name)
        }
    }
    
    /// 生成服务列表键前缀
    fn service_list_prefix(&self, namespace: &str, group: Option<&str>) -> String {
        match group {
            Some(g) if !g.is_empty() => format!("service:{}:{}:", namespace, g),
            _ => format!("service:{}:", namespace),
        }
    }
}

impl Default for MemoryServiceStorage {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl ServiceStorage for MemoryServiceStorage {
    async fn register_instance(&self, instance: &ServiceInstance) -> Result<()> {
        trace!("Registering instance: namespace={}, group={}, service={}, instance_id={}", 
               instance.namespace, instance.group_name, instance.service_name, instance.instance_id);
        
        let key = self.instance_key(&instance.namespace, &instance.group_name, &instance.service_name, &instance.instance_id);
        let data = serde_json::to_vec(instance)?;
        
        self.storage.put(&key, &data).await?;
        
        debug!("Registered instance: {}", key);
        Ok(())
    }
    
    async fn deregister_instance(&self, namespace: &str, group: &str, service_name: &str, instance_id: &str) -> Result<()> {
        trace!("Deregistering instance: namespace={}, group={}, service={}, instance_id={}", 
               namespace, group, service_name, instance_id);
        
        let key = self.instance_key(namespace, group, service_name, instance_id);
        self.storage.delete(&key).await?;
        
        debug!("Deregistered instance: {}", key);
        Ok(())
    }
    
    async fn get_instance(&self, namespace: &str, group: &str, service_name: &str, instance_id: &str) -> Result<Option<ServiceInstance>> {
        trace!("Getting instance: namespace={}, group={}, service={}, instance_id={}", 
               namespace, group, service_name, instance_id);
        
        let key = self.instance_key(namespace, group, service_name, instance_id);
        
        if let Some(data) = self.storage.get(&key).await? {
            let instance: ServiceInstance = serde_json::from_slice(&data)?;
            debug!("Found instance: {}", key);
            Ok(Some(instance))
        } else {
            debug!("Instance not found: {}", key);
            Ok(None)
        }
    }
    
    async fn get_all_instances(&self, namespace: &str, group: &str, service_name: &str) -> Result<Vec<ServiceInstance>> {
        trace!("Getting all instances: namespace={}, group={}, service={}", namespace, group, service_name);
        
        let prefix = self.service_prefix(namespace, group, service_name);
        let items = self.storage.scan(&prefix).await?;
        
        let mut instances = Vec::new();
        for (_, data) in items {
            let instance: ServiceInstance = serde_json::from_slice(&data)?;
            instances.push(instance);
        }
        
        debug!("Found {} instances for service: {}", instances.len(), service_name);
        Ok(instances)
    }
    
    async fn update_instance_health(&self, namespace: &str, group: &str, service_name: &str, instance_id: &str, healthy: bool) -> Result<()> {
        trace!("Updating instance health: namespace={}, group={}, service={}, instance_id={}, healthy={}", 
               namespace, group, service_name, instance_id, healthy);
        
        let key = self.instance_key(namespace, group, service_name, instance_id);
        
        if let Some(data) = self.storage.get(&key).await? {
            let mut instance: ServiceInstance = serde_json::from_slice(&data)?;
            instance.healthy = healthy;
            instance.update_time = chrono::Utc::now();
            
            let updated_data = serde_json::to_vec(&instance)?;
            self.storage.put(&key, &updated_data).await?;
            
            debug!("Updated instance health: {} -> {}", key, healthy);
        } else {
            debug!("Instance not found for health update: {}", key);
        }
        
        Ok(())
    }
    
    async fn get_all_services(&self, namespace: &str, group: Option<&str>) -> Result<Vec<String>> {
        trace!("Getting all services: namespace={}, group={:?}", namespace, group);
        
        let prefix = self.service_list_prefix(namespace, group);
        let items = self.storage.scan(&prefix).await?;
        
        let mut services = std::collections::HashSet::new();
        for (key, _) in items {
            // 从键中提取服务名: service:namespace:group:service_name:instance_id
            let parts: Vec<&str> = key.split(':').collect();
            if parts.len() >= 4 {
                services.insert(parts[3].to_string());
            }
        }
        
        let service_list: Vec<String> = services.into_iter().collect();
        debug!("Found {} services for namespace={}, group={:?}", service_list.len(), namespace, group);
        Ok(service_list)
    }

    async fn scan(&self, prefix: &str) -> Result<Vec<(String, Vec<u8>)>> {
        self.storage.scan(prefix).await
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use nacos_core::ServiceInstance;

    fn create_test_instance(service_name: &str, ip: &str, port: u16) -> ServiceInstance {
        ServiceInstance::new(service_name.to_string(), "test-group".to_string(), ip.to_string(), port)
    }

    #[tokio::test]
    async fn test_register_and_get_instance() {
        let storage = MemoryServiceStorage::new();
        let instance = create_test_instance("test-service", "127.0.0.1", 8080);

        storage.register_instance(&instance).await.unwrap();

        let retrieved = storage.get_instance("public", "test-group", "test-service", &instance.instance_id).await.unwrap().unwrap();
        assert_eq!(instance, retrieved);
    }

    #[tokio::test]
    async fn test_deregister_instance() {
        let storage = MemoryServiceStorage::new();
        let instance = create_test_instance("test-service", "127.0.0.1", 8080);
        storage.register_instance(&instance).await.unwrap();

        storage.deregister_instance("public", "test-group", "test-service", &instance.instance_id).await.unwrap();

        let retrieved = storage.get_instance("public", "test-group", "test-service", &instance.instance_id).await.unwrap();
        assert!(retrieved.is_none());
    }

    #[tokio::test]
    async fn test_get_all_instances() {
        let storage = MemoryServiceStorage::new();
        storage.register_instance(&create_test_instance("service-a", "1.1.1.1", 80)).await.unwrap();
        storage.register_instance(&create_test_instance("service-a", "2.2.2.2", 80)).await.unwrap();
        storage.register_instance(&create_test_instance("service-b", "3.3.3.3", 80)).await.unwrap();

        let instances = storage.get_all_instances("public", "test-group", "service-a").await.unwrap();
        assert_eq!(instances.len(), 2);
    }

    #[tokio::test]
    async fn test_update_instance_health() {
        let storage = MemoryServiceStorage::new();
        let instance = create_test_instance("health-service", "4.4.4.4", 80);
        storage.register_instance(&instance).await.unwrap();

        storage.update_instance_health("public", "test-group", "health-service", &instance.instance_id, false).await.unwrap();

        let retrieved = storage.get_instance("public", "test-group", "health-service", &instance.instance_id).await.unwrap().unwrap();
        assert!(!retrieved.healthy);
    }

    #[tokio::test]
    async fn test_get_all_services() {
        let storage = MemoryServiceStorage::new();
        storage.register_instance(&create_test_instance("service-x", "1.1.1.1", 80)).await.unwrap();
        storage.register_instance(&create_test_instance("service-y", "2.2.2.2", 80)).await.unwrap();
        storage.register_instance(&create_test_instance("service-x", "3.3.3.3", 80)).await.unwrap(); // same service, different instance

        let services = storage.get_all_services("public", Some("test-group")).await.unwrap();
        assert_eq!(services.len(), 2);
        assert!(services.contains(&"service-x".to_string()));
        assert!(services.contains(&"service-y".to_string()));
    }
}
